package edu.stanford.prpl.app.prpltalk.ui;

import static java.awt.Font.BOLD;
import static java.awt.Font.PLAIN;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

import javax.imageio.ImageIO;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.stanford.prpl.api.BlobResource;
import edu.stanford.prpl.api.Group;
import edu.stanford.prpl.api.Identity;
import edu.stanford.prpl.api.PRPLAppClient;
import edu.stanford.prpl.app.prpltalk.PRPLTalk;
import edu.stanford.prpl.app.prpltalk.PRPLTalk.BuddyInfo;
import edu.stanford.prpl.common.PRPLProperties;
import edu.stanford.prpl.common.util.StringUtils;
import edu.stanford.prpl.common.util.URIUtils;

public class PrPlTalkGUI extends JFrame {

	private static Log log = LogFactory.getLog(PrPlTalkGUI.class);

	PRPLTalk prplTalk;
	PRPLAppClient prplAppClient;

	JMenuBar prplTalkMenu;
	JDialog popupBox;

	JList buddyList;
	JList resourceList;
	JList previewList;
	JTextArea previewTextArea;

	public PrPlTalkGUI() throws Exception {
		super("PrPl Talk v0.0.0.0.1 - " + PRPLProperties.getProperty("prpl.user.key"));
		this.prplTalk = new PRPLTalk();
		this.prplAppClient = this.prplTalk.getPRPLAppClient();

		// Draw
		this.setBounds(824, 0, 480, 640);
		this.initMenu();
		this.initFrame();
		this.setJMenuBar(this.prplTalkMenu);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	public void start() {
		// this.pack();
		this.setVisible(true);
	}

	public void initFrame() {

		JPanel buddyPanel = initBuddyListPanel();
		JPanel resourcePanel = initResourcePanel();
		JPanel previewPanel = initPreviewPanel();

		JTabbedPane topTabPane = new JTabbedPane();
		topTabPane.addTab("Buddy View", buddyPanel);
		topTabPane.addTab("Resource View", resourcePanel);
		topTabPane.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				JTabbedPane pane = (JTabbedPane) e.getSource();
				// Get current tab
				int sel = pane.getSelectedIndex();
				if (sel == 0)
					updateBuddyListPanel();
				else
					updateResourcePanel();

			}
		});

		JTabbedPane bottomTabPane = new JTabbedPane();
		bottomTabPane.addTab("Preview", previewPanel);
		bottomTabPane.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				updateResourcePanel();
			}
		});

		// this.getContentPane().setLayout(new GridLayout(0,1));
		this.getContentPane().add(topTabPane, BorderLayout.CENTER);
		// this.getContentPane().add(resourcePanel, BorderLayout.CENTER);
		this.getContentPane().add(bottomTabPane, BorderLayout.SOUTH);
		this.getContentPane().setBackground(Color.WHITE);
	}

	private JPanel initResourcePanel() {

		JLabel resourceLabel = new JLabel("Resource List");
		resourceLabel.setFont(new Font("Arial", BOLD, 12));

		this.resourceList = new JList();

		BlobResource[] resources = this.prplTalk.getAllCommunicationResources();

		resourceList.setListData(resources);
		resourceList.setCellRenderer(new ResourceListRenderer());

		JScrollPane resourceScrollPane = new JScrollPane();
		resourceScrollPane.getViewport().add(resourceList);

		JPanel resourcePanel = new JPanel(new BorderLayout());
		resourcePanel.add(resourceLabel, BorderLayout.NORTH);
		resourcePanel.add(resourceScrollPane, BorderLayout.CENTER);

		resourceList.addMouseListener(new MouseListener() {
			@Override
			public void mouseClicked(MouseEvent e) {

				if (e.getButton() == MouseEvent.BUTTON1) {

					BlobResource resource = (BlobResource) resourceList.getSelectedValue();
					log.debug("resourceList clicked (" + e.getClickCount() + "). Item: " + resource);

					if (e.getClickCount() == 1) {
						updatePreview(resource);
						// updatePreviewTextArea(resource);
					}
					if (e.getClickCount() == 2) {
						String sessionId = prplTalk.resourceURI2sessionId(resource.getURI());
						SessionWindow sessionWindow = new SessionWindow(prplTalk, sessionId);
						sessionWindow.start();
					}
				} else if (e.getButton() == MouseEvent.BUTTON2) {

				}

			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseReleased(MouseEvent e) {
			}
		});

		resourceList.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				BlobResource resource = (BlobResource) resourceList.getSelectedValue();
				updatePreviewTextArea(resource);
				log.debug("resourceList selected. Item: " + resource);
			}
		});

		return resourcePanel;
	}

	private void updateResourcePanel() {
		BlobResource[] resources = this.prplTalk.getAllCommunicationResources();
		resourceList.setListData(resources);
		resourceList.updateUI();
	}

	private JPanel initPreviewPanel() {
		// Set up preview
		// JLabel previewLabel = new JLabel("Preview");
		// previewLabel.setFont(new Font("Arial", BOLD, 12));

		this.previewList = new JList();
		previewList.setCellRenderer(new PreviewListRenderer());
		previewList.setBackground(Color.getHSBColor(0.1f, 0.50f, 1f));

		JScrollPane previewScrollPane = new JScrollPane();
		previewScrollPane.getViewport().add(previewList);
		previewScrollPane.setPreferredSize(new Dimension(0, 75));

		this.previewTextArea = new JTextArea();
		previewTextArea.setText("-- No Preview --\n\n\n");
		previewTextArea.setEditable(false);
		previewTextArea.setLineWrap(true);
		// previewTextArea.setBackground(Color.getHSBColor(350, 75, 100));
		previewTextArea.setRows(8);

		JPanel previewPanel = new JPanel(new BorderLayout());
		// previewPanel.add(previewLabel, BorderLayout.NORTH);
		previewPanel.add(previewTextArea, BorderLayout.CENTER);
		previewPanel.add(previewScrollPane, BorderLayout.NORTH);
		previewPanel.setSize(0, 150);

		previewList.addMouseListener(new MouseListener() {
			@Override
			public void mouseClicked(MouseEvent e) {
				Object value = previewList.getSelectedValue();
				log.debug("previewList mouse clicked. Item: " + previewList.getSelectedIndex());

				if (value instanceof BlobResource) {
					updatePreviewTextArea((BlobResource) value);

				} else if (value instanceof Message) {
					updatePreviewTextArea((Message) value);
				}

			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseReleased(MouseEvent e) {
			}
		});

		previewList.addListSelectionListener(new ListSelectionListener() {

			public void valueChanged(ListSelectionEvent e) {
				Object value = previewList.getSelectedValue();
				log.debug("previewList mouse clicked. Item: " + previewList.getSelectedIndex());

				if (value instanceof BlobResource) {
					updatePreviewTextArea((BlobResource) value);

				} else if (value instanceof Message) {
					updatePreviewTextArea((Message) value);
				}
			}
		});

		return previewPanel;
	}

	private JPanel initBuddyListPanel() {
		// Set up buddy list
		JLabel buddyLabel = new JLabel("Buddy List");
		buddyLabel.setFont(new Font("Arial", BOLD, 12));

		this.buddyList = new JList();
		buddyList.setFont(new Font("Arial", PLAIN, 12));
		buddyList.setListData(this.prplTalk.getBuddyList());
		buddyList.setCellRenderer(new BuddyListRenderer());

		JScrollPane buddyListcrollPane = new JScrollPane();
		buddyListcrollPane.getViewport().add(buddyList);

		JPanel buddyPanel = new JPanel(new BorderLayout());
		buddyPanel.add(buddyLabel, BorderLayout.PAGE_START);
		buddyPanel.add(buddyListcrollPane, BorderLayout.CENTER);

		buddyList.addMouseListener(new MouseListener() {
			@Override
			public void mouseClicked(MouseEvent e) {

				if (e.getButton() == MouseEvent.BUTTON1) {

					BuddyInfo buddy = (BuddyInfo) buddyList.getSelectedValue();
					log.debug("BuddyList clicked (" + e.getClickCount() + "). Item: " + buddy);

					if (e.getClickCount() == 1) {
						updatePreview(buddy);
					}
					if (e.getClickCount() == 2) {
						BuddyWindow buddyWindow = new BuddyWindow(prplTalk, buddy);
						buddyWindow.start();
					}
				} else if (e.getButton() == MouseEvent.BUTTON3) {

					log.debug("BuddyList right clicked (" + e.getClickCount() + ")");

					JPopupMenu popupMenu = new JPopupMenu();
					JMenuItem startSession = new JMenuItem("Start Session");
					startSession.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							Object[] buddies = buddyList.getSelectedValues();
							String[] identityURIs = new String[buddies.length];
							if (buddies != null) {
								for (int i = 0; i < buddies.length; i++) {
									BuddyInfo buddy = (BuddyInfo) buddies[i];
									identityURIs[i] = buddy.identity.getURI();
								}

								String sessionId = prplTalk.startSession(identityURIs);
								SessionWindow sessionWindow = new SessionWindow(prplTalk, sessionId);
								sessionWindow.start();
							}
						}
					});

					JMenuItem syncWith = new JMenuItem("Sync With");
					startSession.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							Object[] buddies = buddyList.getSelectedValues();
							if (buddies != null) {
								for (int i = 0; i < buddies.length; i++) {
									BuddyInfo buddy = (BuddyInfo) buddies[i];
									prplTalk.synchWith(buddy.identity.getURI());
								}
							}
						}
					});

					popupMenu.add(startSession);
					popupMenu.add(syncWith);
					popupMenu.show(buddyList, e.getX(), e.getY());
				}
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseReleased(MouseEvent e) {
			}
		});

		buddyList.addListSelectionListener(new ListSelectionListener() {

			public void valueChanged(ListSelectionEvent e) {
				BuddyInfo buddy = (BuddyInfo) buddyList.getSelectedValue();
				updatePreview(buddy);
				log.debug("BuddyList selected. Item: " + buddy);
			}

		});

		return buddyPanel;

	}

	private void updateBuddyListPanel() {
		buddyList.setListData(this.prplTalk.getBuddyList());
	}

	private void updatePreview(BuddyInfo buddy) {
		if (buddy == null)
			return;
		previewList.setListData(buddy.msgResources);
		String previewText = new String();
		previewText += "Buddy Name: " + StringUtils.trimEvenNull(buddy.name);
		previewText += "\nBuddy PrPl Id: " + StringUtils.trimEvenNull(buddy.identity.getKey());
		previewText += "\nNumber of Sessions: " + (buddy.numOfMsg);
		previewTextArea.setText(previewText);
	}

	private void updatePreview(BlobResource resource) {
		if (resource == null)
			return;
		String sessionId = prplTalk.resourceURI2sessionId(resource.getURI());
		Message[] messages = prplTalk.getMessages(sessionId, true);
		previewList.setListData(messages);
		updatePreviewTextArea(resource);
	}

	private void updatePreviewTextArea(BlobResource resource) {

		if (resource == null)
			return;

		String sessionId = prplTalk.resourceURI2sessionId(resource.getURI());
		Message[] messages = prplTalk.getMessages(sessionId, true);

		if (messages != null && messages.length > 0) {
			Message lastMessage = messages[messages.length - 1];
			this.updatePreviewTextArea(lastMessage);
		}
		// previewTextArea.setText("Most Recent " + previewTextArea.getText());
	}

	private void updatePreviewTextArea(Message message) {

		if (message == null)
			return;

		String previewText = new String();

		try {
			// previewText = "Message at " + message.getSentDate() + " to " + Arrays.toString(message.getFrom()) +
			previewText = "Content of Most Recently Message:\n=========================================\n"
					+ message.getContent().toString();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (MessagingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		previewTextArea.setText(previewText);
	}

	public void initMenu() {
		JMenuBar menu = new JMenuBar();
		JMenu pt = new JMenu("PrPlTalk");
		JMenu help = new JMenu("Help");

		JMenuItem about = new JMenuItem("About");
		about.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showpopupBox();
			}
		});

		JMenuItem addBuddy = new JMenuItem("Add Buddy");
		addBuddy.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showAddBuddyBox();
			}
		});

		JMenuItem quit = new JMenuItem("Quit");
		quit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});

		pt.add(addBuddy);
		pt.add(quit);
		help.add(about);

		menu.add(pt);
		menu.add(help);
		this.prplTalkMenu = menu;
	}

	private void showpopupBox() {
		popupBox = new JDialog(this, "About PrPlTalk", true);
		JPanel msgPanel = new JPanel();
		JPanel btnPane = new JPanel();

		JTextArea jArea = new JTextArea();
		jArea.setText("CS294s - PrPlTalk");
		jArea.setEditable(false);
		msgPanel.add(jArea);

		JButton ok = new JButton("OK");
		btnPane.add(ok);
		ok.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				popupBox.setVisible(false);
				popupBox.dispose();
			}
		});

		popupBox.setLocation(320, 240);
		popupBox.getContentPane().add(msgPanel);
		popupBox.getContentPane().add(btnPane, BorderLayout.SOUTH);
		popupBox.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		popupBox.pack();
		popupBox.setVisible(true);
	}

	private void showAddBuddyBox() {
		popupBox = new JDialog(this, "Add Buddy", true);
		JPanel msgPanel = new JPanel();
		JPanel btnPane = new JPanel();

		JLabel buddyIdLabel = new JLabel("Buddy Id");
		JLabel buddyNameLabel = new JLabel("Buddy Name");

		final JTextField buddyIdTextField = new JTextField();
		buddyIdTextField.setColumns(10);
		final JTextField buddyNameTextField = new JTextField();
		buddyNameTextField.setColumns(10);

		msgPanel.add(buddyIdLabel);
		msgPanel.add(buddyIdTextField);
		msgPanel.add(buddyNameLabel);
		msgPanel.add(buddyNameTextField);

		JButton ok = new JButton("OK");
		btnPane.add(ok);
		ok.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String buddyKey = StringUtils.trimEvenNull(buddyIdTextField.getText());
				String buddyName = StringUtils.trimEvenNull(buddyNameTextField.getText());
				if (buddyKey.length() > 0) {
					String buddyURI = URIUtils.getIdentityURI(buddyKey);
					Identity identity = prplAppClient.getIdentityManager().getIdentityByURI(buddyURI, true);
					identity.setName(buddyName);
				}
				updateBuddyListPanel();
				popupBox.setVisible(false);
				popupBox.dispose();
			}
		});

		JButton cancel = new JButton("Cancel");
		btnPane.add(cancel);
		cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				popupBox.setVisible(false);
				popupBox.dispose();
			}
		});

		popupBox.setLocation(320, 240);
		popupBox.getContentPane().add(msgPanel);
		popupBox.getContentPane().add(btnPane, BorderLayout.SOUTH);
		popupBox.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		popupBox.pack();
		popupBox.setVisible(true);
	}

	public static class ResourceListRenderer extends javax.swing.DefaultListCellRenderer {
		@Override
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
				boolean cellHasFocus) {

			JPanel p = new JPanel(new BorderLayout());
			JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

			try {
				BufferedImage icon = ImageIO.read(new FileInputStream("img/message.gif"));
				l.setIcon(new ImageIcon(icon));
				// icon = ImageIO.read(ClassLoader.getSystemClassLoader().getResource("img/message.gif"));

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			BlobResource resource = (BlobResource) value;
			Object[] metadata = resource.getMetaData(PRPLTalk.PROPERTY_SESSION_ID_URI);
			String sid = (metadata.length > 0) ? metadata[0].toString() : "";
			metadata = resource.getMetaData(PRPLTalk.PROPERTY_RECIPIENT_URI);
			Object[] recipients = metadata;

			String text = new String();
			text = resource.getLastModifiedDate().getTime().toString() + "\n" + "SessionId: " + sid + "\n"
					+ "Owner: " + resource.getOwner().getKey() + "\n" + "Recp: " + Arrays.toString(recipients);

			JTextPane t = new JTextPane();
			t.setText(text);
			t.setFont(new Font("Arial", PLAIN, 11));

			p.add(l, BorderLayout.NORTH);
			p.add(t, BorderLayout.CENTER);

			return p;
		}
	}

	public static class BuddyListRenderer extends javax.swing.DefaultListCellRenderer {

		@Override
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
				boolean cellHasFocus) {

			JLabel c = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
			BuddyInfo buddy = (BuddyInfo) value;

			try {
				if (buddy.photoResource != null) {
					BufferedImage icon = ImageIO.read(buddy.photoResource.getBlob());
					c.setIcon(new ImageIcon(icon.getScaledInstance(55, 55, Image.SCALE_DEFAULT)));
				} else {
					// BufferedImage icon =
					// ImageIO.read(ClassLoader.getSystemClassLoader().getResource("img/buddy.jpg"));
					BufferedImage icon = ImageIO.read(new FileInputStream("img/buddy.jpg"));
					c.setIcon(new ImageIcon(icon));
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			c.setText(buddy.name + "\t [" + buddy.numOfMsg + "]");
			return c;
		}
	}

	public static class PreviewListRenderer extends javax.swing.DefaultListCellRenderer {
		@Override
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
				boolean cellHasFocus) {

			JLabel c = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

			if (value instanceof BlobResource) {
				BlobResource resource = (BlobResource) value;

				StringBuffer buffer = new StringBuffer("Me");
				Group[] groups = resource.getSharingGroups();
				Identity[] identities = resource.getSharingIdentities();

				for (Group group : groups) {
					buffer.append(", ").append(group.getName());
				}
				for (Identity identity : identities) {
					String name = (identity.getName() == null) ? identity.getKey() : identity.getName();
					buffer.append(", ").append(name);
				}

				String text = new String();
				text = (index + 1) + ". Session at " + resource.getLastModifiedDate().getTime().toString()
						+ " with [" + buffer.toString() + "]";
				c.setText(text);

			} else if (value instanceof Message) {
				Message message = (Message) value;

				try {
					String text = (index + 1) + ". Message at " + message.getSentDate() + " from "
							+ Arrays.toString(message.getFrom());
					c.setText(text);
				} catch (MessagingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			return c;
		}
	}
}
